/*
 * WeightHistoryComponent.java
 *
 * Created on 10 de Julho de 2011, 12:29
 */

package intopo.demonstrator.partnerclassification.gui;

import intopo.demonstrator.partnerclassification.State;
import intopo.demonstrator.partnerclassification.Parameters;
import intopo.demonstrator.partnerclassification.Partner;
import java.awt.event.MouseEvent;

import util.math.Rational;
import util.gui.Plot2D;

import java.awt.*;
import java.beans.*;
import java.io.Serializable;

/**
 * A component that displays the history of the partner weight vector.
 *
 * @author pedro
 */
public class WeightHistoryComponent
	extends AbstractStateHistoryComponent
	implements Serializable
{
	public WeightHistoryComponent ()
	{
		setYLabel ("weight");
		setTitle ("Weight Vector");
		setYRange (0, 1);
		setYTics (0, 0.2, 1);
		Listener l = new Listener ();
		this.addMouseListener (l);
		this.addMouseMotionListener (l);
		for (Partner p : Model.parameters.getPartners()) {
			addData (new LinePartner (p));
		}
	}
	/**
	 * Sets the parameters and resets the data shown by the {@code Plot2D} component.
	 */
	@Override
	public void parametersChanged ()
	{
		// figure a reasonable step
		int exp = -Model.parameters.getNumberBitsWeight ();
		double step;
		do {
			step = Math.pow (2, exp);
			exp++;
		} while (1 / step > plotArea.height / 10 && step < 1);
		setYTics (0, step, 1);
		// ...
		clearData ();
		for (Partner p : Model.parameters.getPartners()) {
			addData (new LinePartner (p));
		}
		super.parametersChanged ();
	}
	public void paintHistory (Graphics g)
	{
	}
	/**
	 *  Return the line color that corresponds to the given partner.
	 * @param p The partner whose color is returned
	 * @return the line color that corresponds to the given partner.
	 */
	static private Color partnerColor (Partner p)
	{
		Rational green = p.getBehaveAcceptablyProbability ();
		return new Color (0, green.toBigDecimal ().floatValue (), 0);
	}
	/**
	 * A class that represents a line in the plot.  Each line represents the weight variation of a partner.
	 */
	final private class LinePartner
	  extends Plot2D.AbstractData
	{
		/**
		 * The partner whose weight is being shown.
		 */
		private final Partner partner;
		/**
		 * Construct a new line.
		 * @param partner
		 */
		LinePartner (Partner partner)
		{
			super (null, partnerColor (partner), null, false, true, false);
			this.partner = partner;
		}
		public int size ()
		{
			return Model.history.size();
		}
		public double x (int i)
		{
			return i;
		}
		public double y (int i)
		{
			State s = Model.getHistory (i);
			return s.getWeightAsDouble (partner);
		}
	}
	/**
	 * Listener responsible for updating the tool tip text when the mouse moves.
	 */
	private class Listener
		extends java.awt.event.MouseAdapter
	{
		@Override
		public void mouseMoved (MouseEvent mouseEvent)
		{
			int x = mouseEvent.getX ();
			x /= 2;
			if (x >= Model.history.size ()) {
				return ;
			}
			int height = getHeight ();
			Rational distance = new Rational (Integer.MAX_VALUE);
			Rational mouse = new Rational (mouseEvent.getY ());
			String toolTip = null;
			State state = Model.getHistory (x);
			for (Partner p : Model.parameters.getPartners ()) {
				x = 0;
				Rational w = state.getWeightAsRational (p).multiply (new Rational (height));
				Rational d = w.subtract (mouse).abs ();
				if (d.compareTo (distance) < 0) {
					toolTip = p.toString ();
					distance = d;
				}
				else if (d.compareTo (distance) == 0) {
					toolTip += "  " + p.toString ();
				}
			}
			if (distance.compareTo (MIN_DISTANCE_R) <= 0) {
				setToolTipText (toolTip);
			}
			else {
				setToolTipText (null);
			}
		}
	}
}
